//
//  HttpClient.swift
//  HFUTER
//
//  Created by HD on 15/1/26.
//  Copyright (c) 2015年 HD. All rights reserved.
//

import UIKit

public enum HTTPMethod: String {
    case GET = "GET"
    case POST = "POST"
    case PUT = "PUT"
    case HEAD = "HEAD"
    case DELETE = "DELETE"
}

/// Object representation of a HTTP Response.
class HttpResponse: NSObject {
    /// The headers values in HTTP response.
    var headers: Dictionary<String,String>?
    /// The mime type of the HTTP response.
    var mimeType: String?
    /// The suggested filename for a downloaded file.
    var suggestedFilename: String?
    /// The body or response data of the HTTP Response.
    var data: NSMutableData?
    /// The status code of the HTTP Response.
    var statusCode: Int?
    /// Returns the response as a string
    func text() -> String? {
        if let d = self.data {
            return  NSString(data: d, encoding: NSUTF8StringEncoding) as? String
        }
        return nil
    }
    func text(encoding: NSStringEncoding) -> String! {
        if let d = self.data {
            return  NSString(data: d, encoding: encoding) as! String
        }
        return nil
    }
    /// The URL of the HTTP Response.
    var URL: NSURL?
}

class HttpError: NSError {
    override init(domain: String, code: Int, userInfo dict: [NSObject : AnyObject]?) {
        super.init(domain: domain, code: code, userInfo: dict)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class HttpClient: NSObject, NSObjectProtocol, NSURLConnectionDataDelegate {
    
    private var response: ((HttpResponse) -> Void)!
    private var error: ((HttpError) -> Void)!
    private let res = HttpResponse()
    
    //重定向url，当遇到这个url则结束
    var redirectUrl: String! = nil
    
    func Get(url: String, cookie: String, response: (response: HttpResponse) -> Void, error: (error: HttpError) -> Void) {
        Get(url, requestHeaders: ["Cookie": cookie], response: response, error: error)
    }
    
    func Get(url: String, requestHeaders headers: Dictionary<String, String>! = nil, response: (response: HttpResponse) -> Void, error: (error: HttpError) -> Void) {
        let URL = NSURL(string: url)
        var request = NSMutableURLRequest(URL: URL!)
        request.HTTPMethod = HTTPMethod.GET.rawValue
        //添加HTTP头
        if headers != nil {
            for (key, value) in headers {
                request.addValue(value, forHTTPHeaderField: key)
            }
        }
        let conn = NSURLConnection(request: request, delegate: self)
        self.response = response
        self.error = error
        conn?.start()
    }
    
    func Post(url: String, cookie: String, paras: Dictionary<String, AnyObject>!, response: (response: HttpResponse) -> Void, error: (error: HttpError) -> Void) {
        Post(url, headers: ["Cookie": cookie], para: createHttpBody(paras), response: response, error: error)
    }
    
    func Post(url: String, paras: Dictionary<String, AnyObject>!, response: (response: HttpResponse) -> Void, error: (error: HttpError) -> Void) {
        Post(url, headers: nil, para: createHttpBody(paras), response: response, error: error)
    }
    
    func Post(url: String, para: NSData, response: (response: HttpResponse) -> Void, error: (error: HttpError) -> Void) {
        Post(url, headers: nil, para: para, response: response, error: error)
    }
    
    func Post(url: String, headers: Dictionary<String, String>!, para: NSData, response: (response: HttpResponse) -> Void, error: (error: HttpError) -> Void) {
        let URL = NSURL(string: url)
        var request = NSMutableURLRequest(URL: URL!)
        request.HTTPMethod = HTTPMethod.POST.rawValue
        if headers != nil {
            for (key, value) in headers {
                request.addValue(value, forHTTPHeaderField: key)
            }
        }
        request.HTTPBody = para
        let conn = NSURLConnection(request: request, delegate: self)
        self.response = response
        self.error = error
        conn?.start()
    }
    
    private func createHttpBody(paras: Dictionary<String, AnyObject>) -> NSData {
        var str = ""
        for (key, value) in paras {
            str += "\(key)=\(value)&"
        }
        if str.length > 0 {
            str = str.subStringToIndex(str.length - 1)
        }
        return (str as NSString).dataUsingEncoding(NSUTF8StringEncoding)!
    }
    
    // 普通下载
    func Download(url: String, headers: Dictionary<String, String>!, response: (response: HttpResponse) -> Void, error: (error: HttpError) -> Void) {
        self.Get(url, requestHeaders: headers, response: response, error: error)
    }
    
    ///接收到数据
    func connection(connection: NSURLConnection, didReceiveData data: NSData) {
        if response != nil {
            if res.data == nil {
                res.data = NSMutableData()
            }
            res.data?.appendData(data)
        }
    }
    
    //失败
    func connection(connection: NSURLConnection, didFailWithError error: NSError) {
        ThreadUtil.mainThread { () -> Void in
            self.error(HttpError(domain: error.domain, code: error.code, userInfo: error.userInfo))
        }
    }
    
    func connection(connection: NSURLConnection, willSendRequest request: NSURLRequest, redirectResponse response: NSURLResponse?) -> NSURLRequest? {
        if redirectUrl == nil {
            return request
        } else {
            if response?.URL?.absoluteString == redirectUrl {
                return nil
            } else {
                return request
            }
        }
    }
    
    //接收到的反应
    func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
        if self.response != nil {
            if let httpResponse = response as? NSHTTPURLResponse {
                res.headers = httpResponse.allHeaderFields as? Dictionary<String, String>
                res.mimeType = httpResponse.MIMEType
                res.suggestedFilename = httpResponse.suggestedFilename
                res.statusCode = httpResponse.statusCode
                res.URL = httpResponse.URL
            }
        }
    }
    
    //连接结束
    func connectionDidFinishLoading(connection: NSURLConnection) {
        ThreadUtil.mainThread { () -> Void in
            self.response(self.res)
        }
    }
}